package com.ruoyi.teaching.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.li.work.domain.vo.WorkDeptUserVO;
import com.ruoyi.li.work.mapper.SysUserMapper;
import com.ruoyi.teaching.domain.*;
import com.ruoyi.teaching.domain.vo.*;
import com.ruoyi.teaching.mapper.*;
import com.ruoyi.teaching.service.PlatformTTaskService;
import com.ruoyi.teaching.utils.UniversalUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 王旭
 * @since 2024-06-18
 */
@Service
public class PlatformTTaskServiceImpl extends ServiceImpl<PlatformTTaskMapper, PlatformTTask> implements PlatformTTaskService {

    @Autowired
    private PlatformTTaskMapper platformTTaskMapper;

    @Autowired
    private PlatformTTaskDeptMapper platformTTaskDeptMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private PlatformTScoreMapper platformTScoreMapper;

    @Autowired
    private PlatformTTaskQuestionMapper platformTTaskQuestionMapper;

    @Autowired
    private PlatformQQuestionMapper platformQQuestionMapper;


    @Override
    public AjaxResult selectPlatformTTaskList(Integer pageNum, Integer pageSize, String taskName, Integer taskCourse, Integer taskChapter, Integer taskPart) {
        // 创建查询条件
        QueryWrapper<PlatformTTask> queryWrapper = new QueryWrapper<>();
        Page<PlatformTTask> taskPage = new Page<>(pageNum, pageSize);

        // 获取当前用户ID
        int userId = SecurityUtils.getUserId().intValue();
        queryWrapper.eq("create_id", userId);

        // 添加查询条件
        if (taskName != null && !taskName.isEmpty()) {
            queryWrapper.like("task_name", taskName);
        }
        if (taskCourse != null) {
            queryWrapper.eq("task_course", taskCourse);
        }
        if (taskChapter != null) {
            queryWrapper.eq("task_chapter", taskChapter);
        }
        if (taskPart != null) {
            queryWrapper.eq("task_part", taskPart);
        }
        // 根据 id 字段倒序排序
        queryWrapper.orderByDesc("id");

        // 分页查询作业
        taskPage = platformTTaskMapper.selectPage(taskPage, queryWrapper);

        // 创建返回结果的分页对象
        Page<PlatformTTaskInVO> taskInVOPage = new Page<>(pageNum, pageSize);
        BeanUtils.copyProperties(taskPage, taskInVOPage);

        // 转换查询结果为 VO 对象
        List<PlatformTTaskInVO> taskInVOList = new ArrayList<>();
        for (PlatformTTask record : taskPage.getRecords()) {
            PlatformTTaskInVO taskInVO = new PlatformTTaskInVO();
            BeanUtils.copyProperties(record, taskInVO);

            // 获取作业关联的班级ID
            Integer[] deptIds = platformTTaskDeptMapper.selectByTaskId(record.getId());
            taskInVO.setDeptIds(deptIds);

            taskInVOList.add(taskInVO);
        }
        taskInVOPage.setRecords(taskInVOList);

        // 返回查询结果
        return new AjaxResult(HttpStatus.SUCCESS, "查询成功", taskInVOPage);
    }


    @Override
    public AjaxResult selectPlatformTTaskById(Long id) {
        PlatformTTaskOutVO platformTTaskOutVO = new PlatformTTaskOutVO();
        PlatformTTask platformTTask = platformTTaskMapper.selectById(id);
        if (platformTTask == null) {
            return new AjaxResult(HttpStatus.ERROR, "未找到相关作业信息");
        }
        BeanUtils.copyProperties(platformTTask, platformTTaskOutVO);
        if(platformTTask.getTaskType() == 0){
            Integer taskId = platformTTask.getId();
            List<PlatformTTaskQuestion> questions = platformTTaskQuestionMapper.selectByTaskId(taskId);
            // 创建题目输出对象列表
            List<QuestionOutVO> questionOutVOS = new ArrayList<>();
            for (PlatformTTaskQuestion question: questions) {
                // 查询具体题目信息
                PlatformQQuestion platformQQuestion = platformQQuestionMapper.selectById(question.getQuestionId());
                if (platformQQuestion != null) {
                    // 复制题目信息到输出对象
                    PlatformQQuestionVO platformQQuestionVO = UniversalUtil.stringToArray(platformQQuestion);
                    QuestionOutVO questionOutVO = new QuestionOutVO();
                    BeanUtils.copyProperties(platformQQuestionVO, questionOutVO);
                    questionOutVO.setQuestionValue(question.getQuestionValue());
                    questionOutVOS.add(questionOutVO);
                }
            }
            platformTTaskOutVO.setPlatformTTaskQuestions(questionOutVOS);
        }
        //将该作业的班级塞入
        int i = id.intValue();
        Integer[] deptIds = platformTTaskDeptMapper.selectByTaskId(i);
        platformTTaskOutVO.setDeptIds(deptIds);

        return new AjaxResult(HttpStatus.SUCCESS,"查询成功",platformTTaskOutVO);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public AjaxResult insertPlatformTTask(PlatformTTaskInVO platformTTaskVO) {
        // 创建并设置作业对象
        PlatformTTask platformTTask = new PlatformTTask();
        BeanUtils.copyProperties(platformTTaskVO, platformTTask);

        // 获取并设置发布人信息
        UniversalCreateUpdate createUpdate = UniversalUtil.getCreateUpdate(sysUserMapper);
        platformTTask.setCreateBy(createUpdate.getName());
        platformTTask.setCreateId(createUpdate.getId());
        platformTTask.setCreateTime(DateUtils.getNowDate());

        // 插入作业记录
        int insertResult = platformTTaskMapper.insert(platformTTask);
        if (insertResult == 0) {
            throw new RuntimeException("新增失败");
        }

        // 获取作业ID
        Integer taskId = platformTTask.getId();

        // 添加班级和作业的关联关系
        Integer[] deptIds = platformTTaskVO.getDeptIds();
        for (Integer deptId : deptIds) {
            PlatformTTaskDept taskDept = new PlatformTTaskDept();
            taskDept.setDeptId(deptId);
            taskDept.setTaskId(taskId);
            platformTTaskDeptMapper.insertInTaskDept(taskDept);
        }

        // 将作业分配给班级中的每位学生
        for (Integer deptId : deptIds) {
            assignTaskToStudentsInDept(deptId, platformTTaskVO, createUpdate, taskId);
        }

        return new AjaxResult(HttpStatus.SUCCESS, "新增成功");
    }

    /**
     * 为班级中的每位学生分配作业
     *
     * @param deptId 班级ID
     * @param platformTTaskVO 作业输入对象
     * @param createUpdate 创建人信息
     * @param taskId 作业ID
     */
    private void assignTaskToStudentsInDept(Integer deptId, PlatformTTaskInVO platformTTaskVO, UniversalCreateUpdate createUpdate, Integer taskId) {
        String deptIdLong = String.valueOf(deptId);
        List<SysUser> studentsOld = sysUserMapper.selectUserByDeptId(deptIdLong);
        List<SysUser> students = new ArrayList<>();
        studentsOld.stream().filter(distinctByKey(SysUser::getUserId)) //filter保留true的值
                .forEach(students::add);

        for (SysUser student : students) {
            // 创建并设置成绩对象
            PlatformTScore score = new PlatformTScore();
            BeanUtils.copyProperties(platformTTaskVO, score);
            score.setCreateBy(createUpdate.getName());
            score.setCreateId(createUpdate.getId());
            score.setCreateTime(DateUtils.getNowDate());
            score.setTaskId(taskId);
            score.setTaskStatus(0); // 未完成状态
            score.setStudentId(student.getUserId().intValue());
            score.setDeptId(deptId);
            score.setVettingStatus(0); // 未审核状态

            // 处理题库作业
            if (platformTTaskVO.getTaskType() == 0) {
                List<ScoreInfoInVO> scoreInfoList = new ArrayList<>();
                for (PlatformTTaskQuestion taskQuestion : platformTTaskVO.getPlatformTTaskQuestions()) {
                    // 检查是否已存在相同的任务题目
                    boolean exists = platformTTaskQuestionMapper.existsTaskQuestion(taskId, taskQuestion.getQuestionId());
                    if (!exists) {
                        taskQuestion.setTaskId(taskId);
                        platformTTaskQuestionMapper.insertToTaskQuestion(taskQuestion); // 插入新题目
                    }

                    // 组合试卷信息
                    ScoreInfoInVO scoreInfo = new ScoreInfoInVO();
                    scoreInfo.setId(taskQuestion.getQuestionId());
                    scoreInfo.setQuestionValue(taskQuestion.getQuestionValue());
                    scoreInfoList.add(scoreInfo);
                }
                score.setScoreInfo(JSON.toJSONString(scoreInfoList, SerializerFeature.WriteMapNullValue));
            }

            // 插入成绩记录
            platformTScoreMapper.insert(score);
        }
    }

    static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        Map<Object,Boolean> seen = new ConcurrentHashMap<>();
        //putIfAbsent方法添加键值对，如果map集合中没有该key对应的值，则直接添加，并返回null，如果已经存在对应的值，则依旧为原来的值。
        //如果返回null表示添加数据成功(不重复)，不重复(null==null :TRUE)
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }


    @Override
    public AjaxResult deletePlatformTTaskByIds(Long[] ids) {
        // 记录成功删除的作业数量
        int successCount = 0;

        for (Long id : ids) {
            // 删除作业记录
            int deleteCount = platformTTaskMapper.deleteById(id);
            if (deleteCount > 0) {
                successCount++;
                // 删除作业和题目的关联
                platformTTaskQuestionMapper.deleteByTaskId(id);
                // 删除班级和作业的关联
                platformTTaskDeptMapper.deleteByTaskId(id);
                // 删除作业成绩
                platformTScoreMapper.deleteByTaskId(id);
            }
        }

        // 检查是否所有作业都成功删除
        if (successCount == ids.length) {
            return new AjaxResult(HttpStatus.SUCCESS, "删除成功");
        } else {
            throw new RuntimeException("删除失败");
        }
    }
}
